/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.action.retrieve;


import com.inspur.edp.bef.api.action.VoidActionResult;
import com.inspur.edp.bef.api.action.assembler.IBEActionAssembler;
import com.inspur.edp.bef.api.be.IBEContext;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveParam;
import com.inspur.edp.bef.core.action.base.ActionUtil;
import com.inspur.edp.bef.core.be.CoreBEContext;
import com.inspur.edp.bef.spi.action.AbstractAction;
import com.inspur.edp.bef.spi.action.assembler.retrieve.RetrieveActionAssembler;
import com.inspur.edp.cef.entity.entity.IEntityData;

public class RetrieveWithScopeAction extends AbstractAction<VoidActionResult> {

	//region Constructor
	public RetrieveWithScopeAction(IBEContext beContext, RetrieveParam para) {
		this.para = para;
	}


	//endregion


	//region 字段属性
	private RetrieveParam para;

	//endregion


	//region Override

	@Override
	public final void execute() {
		CoreBEContext beContext = (CoreBEContext) ActionUtil.getBEContext(this);

		if (beContext.hasData()) {//①有数据
			if (beContext.isDeleted()) {
				return;
			}
			if (para.getForceFromRepository()) {
				beContext.clearData();
				retrieve(beContext);
			} else if (!beContext.hasChange()) {
				if (para.getRetrieveFilter() != null && para.getRetrieveFilter().isEnableMultiLanguage()
						&& !beContext.isMultiLanguaged()) {
					beContext.clearData();
					retrieve(beContext);
				} else {
					checkVersion(beContext);
				}
			}
		} else { //②无数据，去获取
			retrieve(beContext);
		}
	}

	@Override
	protected final IBEActionAssembler getAssembler() {
		return GetAssemblerFactory().getRetrieveActionAssembler(ActionUtil.getBEContext(this), para);
	}


	//endregion


	//region Private

	/**
	 * 批量获取
	 *
	 * @param beContext
	 */
	private void retrieve(IBEContext beContext) {
		RetrieveScopeNodeParameter retrieveScopeNodeParameter = new RetrieveScopeNodeParameter(beContext, para, (ctx, data) -> afterRetrieve(ctx, data));
		ActionUtil.getBEContext(this).addScopeParameter(retrieveScopeNodeParameter);
		((CoreBEContext)beContext).setMultiLanguaged(
				para.getRetrieveFilter() != null && para.getRetrieveFilter().isEnableMultiLanguage());
	}

	/**
	 * 批量加锁
	 *
	 * @param beContext
	 */
	private void checkVersion(CoreBEContext beContext) {
		CheckVersionScopeNodeParameter checkVersionScopeNodeParameter = new CheckVersionScopeNodeParameter(beContext,
				para, (ctx, data) -> afterCheckVersion(ctx,data));
		ActionUtil.getBEContext(this).addScopeParameter(checkVersionScopeNodeParameter);
	}

	/**
	 * 获取后的回调函数，将获取结果置入BEContext
	 *
	 * @param beContext
	 * @param data      获取到的实体
	 */
	private void afterRetrieve(IBEContext beContext, IEntityData data) {
		if (data == null) {
			return;
		}
		RetrieveActionAssembler assembler = (RetrieveActionAssembler) getAssembler();
		if (assembler != null && !assembler.demandDataPermission(data)) {
			return;
		}
		loadData2BEContext(beContext, data);
		//RetrieveResult.DicAccessor.add(beContext.ID, beContext.CurrentData);
	}

	/**
	 * 校验数据版本后的回调函数，若校验失败，需要重新Retrieve,并存入BEContext
	 *
	 * @param beContext
	 * @param data      获取到的实体
	 */
	private void afterCheckVersion(CoreBEContext beContext, IEntityData data) {
		loadData2BEContext(beContext, data);
	}

	private void loadData2BEContext(IBEContext beContext, IEntityData data) {
			//加载到BEContext
			ActionUtil.getRootEntity(this).loadData(data);
			//执行AfterRetrieve时机Determination
			ActionUtil.getRootEntity(this).afterLoadingDeterminate();
		//new ActionFactory().getAfterLoadingDtmAction(((ICoreBEContext)beContext).createDeterminationContext()).do();
	}
	//endregion
}
